from client import WebSocketClient, port
import json

def get_local_ip():
    """
    获取本机在局域网中的 IP 地址（通常为 192.168.x.x 或 10.x.x.x）。
    用于提示开发者服务端可能可通过该 IP 被同一网络下的其他设备访问。
    如果获取失败（如无网络），则返回默认的本地回环地址 127.0.0.1。
    """
    import socket
    try:
        # 创建一个 UDP 套接字（不需要真正发送数据包）
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        # 连接到公共 DNS 服务器（8.8.8.8:80），目的是让系统分配一个本地出口 IP。
        s.connect(("8.8.8.8", 80))
        # 获取套接字本地绑定的 IP 和端口，即本机用于外发的 IP 地址。
        ip = s.getsockname()[0]
        s.close()
        return ip
    except Exception:
        # 如果出现任何异常（如无网络），返回本地回环地址。
        return "127.0.0.1"

class ChatWindow:
    """
    客户端窗口功能：
    1，输入服务端的IP，连接服务端。
    2，发送消息给服务端。
    3，接收服务端的消息。
    4，消息显示区显示记录。
    """
    from PyQt6.QtCore import pyqtSignal
    login_successful = pyqtSignal()

    def __init__(self):
        from PyQt6.uic.load_ui import loadUi
        from PyQt6.QtWidgets import (QMainWindow, QTextEdit, QPushButton, QLineEdit)
        ui: QMainWindow = loadUi('./client.ui')
        self.show = ui.show
        self.setWindowTitle = ui.setWindowTitle
        self.text_display: QTextEdit = ui.text_display  # 消息显示区域（只读）。
        # tab_1，连接服务端功能。
        self.input_server: QLineEdit = ui.input_server  # 输入服务端IP
        self.input_username: QLineEdit = ui.input_username  # 输入用户名
        self.connect_button: QPushButton = ui.connect_button
        self.connect_button.clicked.connect(self.on_connect_clicked)
        self.disconnect_button: QPushButton = ui.disconnect_button
        self.disconnect_button.clicked.connect(lambda: self.client.close())  # 主动断开连接。
        self.input_username.textChanged.connect(lambda: self.connect_button.setEnabled(self.input_username.text() != ''))
        # tab_2，发送消息功能。
        self.input_line: QLineEdit = ui.input_line  # 文本输入框。
        self.input_receiver: QLineEdit = ui.input_receiver  # 输入发送对象。
        self.send_button: QPushButton = ui.send_button  # 发送按钮。
        self.send_button.clicked.connect(self.on_send_clicked)
        # 获取本地ip。
        self.client = WebSocketClient()
        ip = get_local_ip()
        self.text_display.setPlaceholderText(f"本机（{ip}: {port}）")  # 提示ip。
        # ✅ 把信号绑定放在这里，只绑定一次！
        self.client.textMessageReceived.connect(self.on_message_received)
        # 连接成功或失败信号。
        self.client.login_successful.connect(self.toggle_login_status)
        self.client.disconnected.connect(self.toggle_login_status)

    def on_connect_clicked(self):
        """
        连接到服务端。
        """
        username = self.input_username.text()  # 客户端用户名。
        ip = self.input_server.text()  # 服务端ip。
        ip = "127.0.0.1" if ip == '' else ip
        # 如果是客户端角色，创建 WebSocketClient 实例并绑定消息信号。
        self.client.set_username_and_ip(username, ip)
        
    def toggle_login_status(self):
        """
        切换窗口的连接服务端和发送数据的设置。
        """
        status = self.client._is_logged_in

        self.input_username.setEnabled(not status)
        self.input_server.setEnabled(not status)
        self.connect_button.setEnabled(not status)
        self.disconnect_button.setEnabled(status)

        self.input_line.setEnabled(status)  # 开启发送消息按钮。
        self.input_receiver.setEnabled(status)
        self.send_button.setEnabled(status)
        if not status:
            self.text_display.append("❌ 无法连接 WebSocket 服务端。")  # 消息显示区提示无法连接。
        self.setWindowTitle("WebSocket客户端" + 
                            (f" - {self.client.username}" if status else ""))

    def on_send_clicked(self):
        """
        当用户点击发送按钮或按下回车时调用，发送消息给服务端（或由服务端转发）。
        """
        msg = self.input_line.text().strip()
        if not msg:
            return
        to_username: str = self.input_receiver.text().strip()  # 发送目标。
        data = {
                    "type": "chat", 
                    "from_username": self.client.username, 
                    "to_username": to_username,  # 默认由服务端接收。
                    "content": msg
                }
        json_msg = json.dumps(data)  # 转为 JSON 字符串。
        self.client.send_message(json_msg)  # 客户端发送消息到服务端。
        if to_username == "":
            self.append_text(f"➡️ 你: 发送给服务端的消息： {msg}")  # 并在界面显示自己发送的内容。
        else:
            self.append_text(f"💬 你: 发送给用户 {to_username} 的消息： {msg}")  # 并在界面显示自己发送的内容。
        self.input_line.clear()  # 清空输入框。

    def on_message_received(self, json_message: str):
        """
        当客户端收到服务端的jon格式的消息时调用，更新界面显示。
        :param json_message: 消息。
        """
        message = json.loads(json_message)
        if message["type"] == "tip":
            self.append_text(f"<font color='blue'>🤖 接收服务端的消息: {message["context"]}")
            if "用户" in message["context"] and "连接成功" in message["context"]:
                self.login_successful.emit()
        else:
            self.append_text(f"<font color='green'>👤 接收用户 {message["from_username"]} 的消息：{message["context"]}")

    def append_text(self, text: str):
        """
        在消息显示区追加一行文本。
        """
        self.text_display.append(text)

if __name__ == '__main__':
    import sys
    from PyQt6.QtWidgets import QApplication
    app = QApplication(sys.argv)
    window = ChatWindow()
    window.show()
    sys.exit(app.exec())